﻿#region 文件信息

/*----------------------------------------------------------------
//
// 文件名称：
// 文件功能描述：
// 设计要求：
//
// 文 件 名：    DetailItemChangeBaseModel
// 创建者：      杨程
// 创建日期：	    2022/11/1 17:21:18

//----------------------------------------------------------------*/

#endregion

namespace Vampirewal.Core.Models;

/// <summary>
/// 明细项变更基类
/// </summary>
/// <typeparam name="TDto"></typeparam>
public abstract class DetailItemChangeBaseModel<TDto> : TopModel
{
    /// <summary>
    /// 当前项的变更状态
    /// </summary>
    public ChangeType InnerItemChangeType { get; private set; }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="dto"></param>
    public DetailItemChangeBaseModel(TDto dto)
    {
        if (dto == null)
        {
            InnerItemChangeType = ChangeType.Add;
        }
        else
        {
            LoadDTO(dto);
            RefreshSourceValue();
        }
    }

    #region 基础属性

    private string _DtlId;

    /// <summary>
    /// 明细ID
    /// </summary>
    [SugarColumn(IsPrimaryKey = true, IsNullable = false, ColumnDescription = "主键")]
    public string DtlId
    {
        get
        {
            return _DtlId;
        }
        set
        {
            _DtlId = value;
            OnPropertyChanged();
        }
    }

    private string _BillId;

    /// <summary>
    /// 关联单据Id
    /// </summary>
    [SugarColumn(IsNullable = false)]
    public string BillId
    {
        get
        {
            return _BillId;
        }
        set
        {
            _BillId = value;
            OnPropertyChanged();
        }
    }

    #endregion

    /// <summary>
    /// 记录原始值，并刷新变更状态为NoChanged
    /// </summary>
    public void RefreshSourceValue()
    {
        InnerItemChangeType = ChangeType.NoChanged;
        //_sourceValueMD5 = CreateCurrentValueToken();
        GetOldValueByAttribute();
    }

    /// <summary>
    /// 设置当前项为删除状态
    /// </summary>
    public void SetDeleteState()
    {
        InnerItemChangeType = ChangeType.Deleted;
    }

    /// <summary>
    /// 加载DTO，如果这里使用到该DTO，需要在该方法里面实例化
    /// </summary>
    /// <param name="dto">原始的DTO，可以为null</param>
    public abstract void LoadDTO(TDto dto);

    private Dictionary<string, object> OldDic = new Dictionary<string, object>();

    /// <summary>
    /// 通过特性获取初始值
    /// </summary>
    private void GetOldValueByAttribute()
    {
        var Props = this.GetType().GetProperties().Where(w => w.GetCustomAttribute<ListenDetailChangeAttribute>() != null);

        foreach (PropertyInfo prop in Props)
        {
            var att = prop.GetCustomAttribute<ListenDetailChangeAttribute>();

            if (att != null)
            {
                var OldVaule = prop.GetValue(this, null);

                OldDic.Add(att.PropertyName, OldVaule);
            }
        }
    }

    /// <summary>
    /// 比较原始值
    /// </summary>
    /// <returns></returns>
    public bool CompareSourceValue()
    {
        var Props = this.GetType().GetProperties().Where(w => w.GetCustomAttribute<ListenDetailChangeAttribute>() != null);

        bool IsChange = false;

        foreach (PropertyInfo prop in Props)
        {
            if (IsChange)
            {
                continue;
            }

            var Newatt = prop.GetCustomAttribute<ListenDetailChangeAttribute>();

            if (Newatt != null && OldDic.TryGetValue(Newatt.PropertyName, out object OldVaule))
            {
                var NewVaule = prop.GetValue(this, null);

                if (InnerItemChangeType != ChangeType.Deleted && InnerItemChangeType != ChangeType.Add)
                {
                    InnerItemChangeType = NewVaule != OldVaule ? ChangeType.Changed : ChangeType.NoChanged;
                }
            }

            if (InnerItemChangeType != ChangeType.NoChanged)
            {
                IsChange = true;
            }
        }

        return IsChange;
    }
}

/// <summary>
/// 细目变更状态
/// </summary>
public enum ChangeType
{
    /// <summary>
    /// 删除
    /// </summary>
    Deleted = -1,

    /// <summary>
    /// 未变更
    /// </summary>
    NoChanged = 0,

    /// <summary>
    /// 新增
    /// </summary>
    Add = 1,

    /// <summary>
    /// 编辑
    /// </summary>
    Changed = 2
}